/*
* $Id: Start.cpp 2 2009-12-23 13:58:02Z volok-aleksej@yandex.ru $
*
* Copyright 2009 by Volokitin Aleksey
* All rights reserved
*
*/
#include "Common/include.h"

LONG SetExceptInfo(int nId, PEXCEPTION_POINTERS data);
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, __in LPTSTR lpCmdLine, int nCmdShow);

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, __in LPTSTR lpCmdLine, int nCmdShow)
{
	int result = 0;
	BOOL bCorrectExit = FALSE;
	BOOL bFirstInitialise = FALSE;
	IApplication* pApp = IApplication::GetApp();
	do{
		__try{
			if(!bFirstInitialise){
				bFirstInitialise = TRUE;
				result = AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
			}
			else
				AfxGetThread()->Run();
			bCorrectExit = TRUE;
		} __except(SetExceptInfo(AfxGetThread()->m_nThreadID, GetExceptionInformation())) {
			if(MessageBox(NULL, _T("Unhanded Exception. Do you want to go on work?"), _T("Error"), MB_OKCANCEL | MB_ICONERROR) == IDOK)
				bCorrectExit = FALSE;
			else
				bCorrectExit = TRUE;
		}
	}
	while(!bCorrectExit);
	pApp->Free();
	return result;
}

/***************************************************************************************/
/*                             Global Function                                         */
/***************************************************************************************/
static int MaxStackDump = 3072, StackColumns = 4;
void DumpStack(DWORD* pStack){
	FILE* fStack;
	fopen_s(&fStack, "C:\\stack.txt", "wt");
	_ftprintf_s(fStack, _T("nStack\n"));
	__try{
		// Esp contains the bottom of the stack, or at least the bottom of
		// the currently used area.
		DWORD* pStackTop;
		__asm{
			// Load the top (highest address) of the stack from the
			// thread information block. It will be found there in
			// Win9x and Windows NT.
			mov	eax, fs:[4]
			mov pStackTop, eax
		}
		if (pStackTop > pStack + MaxStackDump)
			pStackTop = pStack + MaxStackDump;
		int Count = 0;
		DWORD* pStackStart = pStack;
		int nDwordsPrinted = 0;
		while (pStack + 1 <= pStackTop){
			if ((Count % StackColumns) == 0){
				pStackStart = pStack;
				nDwordsPrinted = 0;
				_ftprintf_s(fStack, _T("0x%08x: "), pStack);
			}
			if ((++Count % StackColumns) == 0 || pStack + 2 > pStackTop){
				_ftprintf_s(fStack, _T("%08x "), *pStack);
				nDwordsPrinted++;
				int n = nDwordsPrinted;
				while (n < 4){
					_ftprintf_s(fStack, _T("         "));
					n++;
				}
				for (int i = 0; i < nDwordsPrinted; i++){
					DWORD dwStack = *pStackStart;
					for (int j = 0; j < 4; j++){
						char c = (char)(dwStack & 0xFF);
						if (c < 0x20 || c > 0x7E)
							c = '.';
						WCHAR w = (WCHAR)c;
						_ftprintf_s(fStack, _T("%c"), w);
						dwStack = dwStack >> 8;
					}
					pStackStart++;
				}
				_ftprintf_s(fStack, _T("\n"));
			}else{
				_ftprintf_s(fStack, _T("%08x "), *pStack);
				nDwordsPrinted++;
			}
			pStack++;
		}
		_ftprintf_s(fStack, _T("\n"));
	}__except(EXCEPTION_EXECUTE_HANDLER){
		_ftprintf_s(fStack, _T("Exception encountered during stack dump.\r\n"));
	}
	fclose(fStack);
}

LONG SetExceptInfo(int nId, PEXCEPTION_POINTERS data){
	DumpStack((DWORD*)data->ContextRecord->Esp);
	return EXCEPTION_EXECUTE_HANDLER;
}

